require 'json'
require 'spoule/accessor'
require 'spoule/enum'
require 'spoule/enums'
require 'spoule/json'

module Spoule
  module Parameter
    class Base
      include Spoule::Json
      include Spoule::Accessor
      
      attr_reader :name
      
      def initialize(type, name, *args)
        @type = type
        @name = name
        @format = args[0] if args.size > 0

        @enums = Enums.new
      end

      def <<(o)
        case o
        when Spoule::Enum
          @enums << o
        else
          raise "Cannot accept objects of type #{o.class}!"
        end
      end

      def repeated?
        @repeated
      end
      def repeated=(v)
        @repeated = v
      end

      def to_json(*opts)
        s  = _format_json_prefix(name, opts)
        s += _format_json_kvp('type', type)
        s += ',' + _format_json_kvp('description', description) if !description.nil?
        s += ',' + _format_json_kvp('default', default) if !default.nil?
        s += ',' + _format_json_kvp('required', required?) if !required?.nil?
        s += ',' + _format_json_kvp('format', format) if !format.nil?
        s += ',' + _format_json_kvp('pattern', pattern) if !pattern.nil?
        s += ',' + _format_json_kvp('minimum', minimum) if !minimum.nil?
        s += ',' + _format_json_kvp('maximum', maximum) if !maximum.nil?
        s += @enums.to_json(opts)
        s += ',' + _format_json_kvp('repeated', repeated?) if !repeated?.nil?
        s += ',' + _format_json_kvp('location', location) if !location.nil?
        s += _format_json_suffix
      end
    end # class Base

    class Any < Base
      def initialize(*args)
        super('any', *args)
      end
    end

    class Array < Base
      def initialize(*args)
        super('array', *args)
      end
    end

    class Boolean < Base
      def initialize(*args)
        super('boolean', *args)
      end
    end

    class Byte < Base
      def initialize(*args)
        super('string', *args, 'byte')
      end
    end

    class DateTime < Base
      def initialize(*args)
        super('string', *args, 'date-time')
      end
    end

    class Double < Base
      def initialize(*args)
        super('number', *args, 'double')
      end
    end

    class Float < Base
      def initialize(*args)
        super('float', *args, 'float')
      end
    end

    class Int32 < Base
      def initialize(*args)
        super('integer', name, 'int32')
        @minimum = -2147483648
        @maximum = 2147483647
      end
    end

    class Int64 < Base
      def initialize(*args)
        super('string', *args, 'int64')
        @minimum = -9223372036854775808
        @maximum = 9223372036854775807
      end
    end

    class String < Base
      def initialize(*args)
        super('string', *args)
      end
    end

    class UInt32 < Base
      def initialize(*args)
        super('integer', *args, 'uint32')
        @minimum = 0
        @maximum = 4294967295
      end
    end

    class UInt64 < Base
      def initialize(*args)
        super('string', *args, 'uint64')
        @minimum = 0
        @maximum = 18446744073709551615 # 2**64 - 1
      end
    end
    
  end # class Parameter
end # module Spoule
